package admin.server.service.impl;

import admin.server.service.UmsResourceService;
import admin.dao.model.*;
import cn.hutool.core.util.BooleanUtil;
import cn.hutool.core.util.StrUtil;
import com.github.pagehelper.PageHelper;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import admin.common.constant.AuthConstant;
import admin.common.vo.PageVo;
import admin.dao.mapper.UmsResourceMapper;
import admin.dao.mapper.UmsRoleMapper;
import admin.dao.mapper.UmsRoleResourceRelationMapper;
import admin.server.enums.ResourceType;
import admin.redis.service.RedisService;

import java.util.*;
import java.util.stream.Collectors;

/**
 * 后台资源管理Service实现类
 * Created by zgb on 2020/2/2.
 */
@Service
public class UmsResourceServiceImpl implements UmsResourceService {
    @Autowired
    private UmsResourceMapper resourceMapper;
    @Autowired
    private UmsRoleMapper roleMapper;

    @Autowired
    private RedisService redisService;


    @Autowired
    private UmsRoleResourceRelationMapper roleResourceRelationMapper;


    public void uniqueCheck(UmsResource record) throws Exception {
        if (Objects.equals(record.getResourceType(), ResourceType.API.getValue())) {
            if (StringUtils.isBlank(record.getUrl())) {
                throw new Exception("后端接口url必填");
            }
        } else if (Objects.equals(record.getResourceType(), ResourceType.BUTTON.getValue())) {
            if (StringUtils.isBlank(record.getComponent())) {
                throw new Exception("前端按钮路径必填");
            }
        }
        if (StringUtils.isBlank(record.getName())) {
            throw new Exception("名称 必填！");
        }
        //更新，不变
        if (record.getId() != null) {
            UmsResource one = resourceMapper.selectByPrimaryKey(record.getId());
            if (Objects.equals(one.getName(), record.getName())) {
                return;
            }
        }
        if (StringUtils.isNotBlank(record.getComponent())) {
            UmsResourceExample umsResourceExample = new UmsResourceExample();
            umsResourceExample.createCriteria().andComponentEqualTo(record.getComponent());
            List<UmsResource> list = resourceMapper.selectByExample(umsResourceExample);
            if (!list.isEmpty()) {
                throw new Exception("前端按钮路径 已存在 请勿重复添加！");
            }

        }
    }


    @Override
    @Transactional(rollbackFor = Exception.class)
    public int create(UmsResource umsResource) throws Exception {
        uniqueCheck(umsResource);
        umsResource.setCreateTime(new Date());
        int count = resourceMapper.insertSelective(umsResource);
        List<Long> umsRoleIds = new ArrayList<>();
        UmsRoleExample umsRoleExample = new UmsRoleExample();
        if (!BooleanUtil.isTrue(umsResource.getNecessaryYn())) {
            umsRoleExample.createCriteria().andSupAdminYnEqualTo(true);
        }
        List<UmsRole> umsRoles = roleMapper.selectByExample(umsRoleExample);
        umsRoleIds.addAll(umsRoles.stream().map(e -> e.getId()).collect(Collectors.toList()));
        for (Long umsRoleId : umsRoleIds) {
            UmsRoleResourceRelation umsRoleResourceRelation = new UmsRoleResourceRelation();
            umsRoleResourceRelation.setRoleId(umsRoleId);
            umsRoleResourceRelation.setResourceId(umsResource.getId());
            roleResourceRelationMapper.insert(umsRoleResourceRelation);
        }
        initResourceRolesMap();
        return count;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public int update(Long id, UmsResource umsResource) throws Exception {
        uniqueCheck(umsResource);
        umsResource.setId(id);
        int count = resourceMapper.updateByPrimaryKeySelective(umsResource);
        initResourceRolesMap();
        return count;
    }

    @Override
    public UmsResource getItem(Long id) {
        return resourceMapper.selectByPrimaryKey(id);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void delete(Long id) {
        resourceMapper.deleteByPrimaryKey(id);
        UmsRoleResourceRelationExample umsRoleResourceRelationExample = new UmsRoleResourceRelationExample();
        umsRoleResourceRelationExample.createCriteria().andResourceIdEqualTo(id);
        roleResourceRelationMapper.deleteByExample(umsRoleResourceRelationExample);
        initResourceRolesMap();
    }

    @Override
    public PageVo<UmsResource> list(Long menuId, Integer resourceType, String nameKeyword, String urlKeyword, Integer pageSize, Integer pageNum) {
        PageHelper.startPage(pageNum, pageSize);
        UmsResourceExample example = new UmsResourceExample();
        UmsResourceExample.Criteria criteria = example.createCriteria();
        if (menuId != null) {
            criteria.andMenuIdEqualTo(menuId);
        }
        if (resourceType != null) {
            criteria.andResourceTypeEqualTo(resourceType);
        }
        if (StrUtil.isNotEmpty(nameKeyword)) {
            criteria.andNameLike('%' + nameKeyword + '%');
        }
        if (StrUtil.isNotEmpty(urlKeyword)) {
            criteria.andUrlLike('%' + urlKeyword + '%');
        }
        List<UmsResource> umsResources = resourceMapper.selectByExample(example);
        return PageVo.restPage(umsResources, umsResources);
    }

    @Override
    public List<UmsResource> listAll() {
        return resourceMapper.selectByExample(new UmsResourceExample());
    }

    /**
     * key: resouce的url
     * value: 角色id_角色名称
     *
     * @return
     */
    @Override
    public Map<String, Set<String>> initResourceRolesMap() {
        Map<String, Set<String>> resourceRoleMap = new TreeMap<>();
        List<UmsResource> resourceList = resourceMapper.selectByExample(new UmsResourceExample());
        List<UmsRole> roleList = roleMapper.selectByExample(new UmsRoleExample());
        List<UmsRoleResourceRelation> relationList = roleResourceRelationMapper.selectByExample(new UmsRoleResourceRelationExample());
        for (UmsResource resource : resourceList) {
            //资源用到的角色
            Set<Long> roleIds = relationList.stream().filter(e -> Objects.equals(resource.getId(), e.getResourceId())).map(UmsRoleResourceRelation::getRoleId).collect(Collectors.toSet());
            List<String> roleNames = roleList.stream().filter(item -> roleIds.contains(item.getId())).map(item -> item.getId() + "_" + item.getName()).collect(Collectors.toList());
            //后端接口URL（用于后端鉴权）
            String[] split = resource.getUrl().split(",");
            for (String url : split) {
                Set<String> value = resourceRoleMap.get(url);
                if (CollectionUtils.isEmpty(value)) {
                    resourceRoleMap.put(url, new HashSet<>(roleNames));
                } else {
                    resourceRoleMap.get(url).addAll(roleNames);
                }
            }
        }
        redisService.del(AuthConstant.RESOURCE_ROLES_MAP_KEY);
        redisService.hSetAll(AuthConstant.RESOURCE_ROLES_MAP_KEY, resourceRoleMap);
        return resourceRoleMap;

    }
}
